import protoRoot from "/src/net/proto/proto";
import {Topic} from "@/utils/MqttUtils";
import VfdStatusBean from "@/bean/VfdStatusBean";
import EdgeStatusBean from "@/bean/EdgeStatusBean";
import DateUtils from "@/utils/DateUtils";
import {AnyType, Command2EnStr} from "@/const/Const";

export const GoogleTypeUrl = 'type.googleapis.com/';

const MqttMessage = protoRoot.lookup('MqttMessage');
const Command = protoRoot.lookup('Command')
const ReportDevStatus = protoRoot.lookup("ReportDevStatus");
const VfdStatus = protoRoot.lookup("VfdStatus");
const EdgeStatus = protoRoot.lookup("EdgeStatus");
const DevType = protoRoot.lookupEnum("DevType");
const WSMessage = protoRoot.lookup("WSMessage");
const Response = protoRoot.lookup("Response");
let cmdAnyMap;

export default class ProtoParseUtils {
    constructor() {
        cmdAnyMap = new Map();
        this.initCmdAnyMap();
    }

    /**
     * 获取单例ProtoParseUtils
     * @returns {ProtoParseUtils}
     */
    static getInstance = () => {
        if (!this.instance) {
            this.instance = new ProtoParseUtils();
        }
        return this.instance;
    };

    /**
     * 初始化Any类型的结构体名称和command对应的map
     */
    initCmdAnyMap = () => {
        cmdAnyMap.set(Command.values.Heartbeat, AnyType.Public);
        cmdAnyMap.set(Command.values.SetFRange, AnyType.FrequencyRange);
        console.log('AnyTypeMap init, ', cmdAnyMap);
    };

    /**
     * object to google/protobuf/any
     * @param cmd command
     * @param value protobuf encode之后的数据
     * @returns {{type_url: string, value: *}}
     */
    obj2Any = (cmd, value) => {
        let type_url = cmdAnyMap.get(cmd);
        if (!type_url) {
            return null
        }
        let any = {
            type_url: GoogleTypeUrl + type_url,
            value: value,
        };
        console.log('obj2any', any);
        return any
    };

    /**
     * 处理mqtt接收到的msg
     * @param topic mqtt topic
     * @param payload 消息体
     * @returns {Promise<any>}
     */
    parseMqttMsg = (topic, payload) => {
        return new Promise((resolve, reject) => {
            let mqttMsg = MqttMessage.decode(payload);
            console.log('Received mqtt msg', mqttMsg);
            //根据不同的topic进行解析proto
            switch (topic) {
                case Topic.DevStatus: {
                    let reportDevStatus = ReportDevStatus.decode(mqttMsg.data.value)
                    let devTpe = reportDevStatus.devType
                    console.log('devType', devTpe, DevType.values.DevVfd)
                    const result = this.parseDevStatus(mqttMsg.edgeId, devTpe, reportDevStatus.data.value);
                    if (result == null) {
                        reject('Unknown device')
                    } else {
                        resolve(result)
                    }
                    break;
                }
                default:
                    reject('Unknown topic');
            }
        });
    };

    /**
     * 解析设备信息
     * @param edgeId
     * @param devType
     * @param data
     * @returns {string|*}
     */
    parseDevStatus = (edgeId, devType, data) => {
        switch (devType) {
            case DevType.values.DevVfd:
                return this.parseVfdStatus(edgeId, data)
            case DevType.values.DevEdge:
                return this.parseEdgeStatus(edgeId, data);
            default:
                return null
        }
    }

    /**
     * 解析mqtt消息中的变频器设备状态更新
     * @param eid edge id
     * @param any
     */
    parseVfdStatus = (eid, any) => {
        let vfdStatus = new VfdStatusBean()
        return Object.assign(vfdStatus, VfdStatus.decode(any))

    }

    /**
     * 解析mqtt消息中的变频器设备状态更新
     * @param eid edge id
     * @param any
     */
    parseEdgeStatus = (eid, any) => {
        let edgeStatus = new EdgeStatusBean()
        return Object.assign(edgeStatus, EdgeStatus.decode(any))
    }


    /**
     * 处理ws接收到的msg {code, response}
     * @param event ws消息体
     */
    parseWsMessage = (event) => {
        return new Promise((resolve, reject) => {
            let reader = new FileReader();
            reader.addEventListener("loadend", () => {
                // reader.result 包含转化为类型数组的blob
                // console.log(reader.result);
                let v = new Uint8Array(reader.result);
                let wsMsg = WSMessage.decode(v);
                let resp = Response.decode(wsMsg.data.value)
                console.log('《《《WebSocket Received Response! ' +
                    DateUtils.getNowTime() + '》》》%c' +
                    'CMD=' + wsMsg.cmd + '(' + Command2EnStr[wsMsg.cmd] + ')\n',
                    'font-size:24px;color:#00ff11;', resp);
                if (wsMsg.cmd) {
                    resolve({cmd: wsMsg.cmd, resp});
                } else {
                    reject('Receive websocket data error')
                }
            });
            reader.readAsArrayBuffer(event.data);
        });
    };
}